import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { merchants } from './merchants.entity';
import { Repository,ILike,FindManyOptions,In  } from 'typeorm';
@Injectable()
export class MerchantsService {
    constructor(
        @InjectRepository(merchants) private readonly merchantsRepository: Repository<merchants>
    ) { }
    /**
     * 异步查找所有商户信息
     * @returns 返回一个包含所有商户的数组
     */
    async findAll(): Promise<merchants[]> {
        return await this.merchantsRepository.find();
    }
     /**
     * 异步查找所有商户信息
     * @param ids 商户的标识符
     * @returns 返回一个包含所有商户的数组
     */
     async findByids(ids:number[]): Promise<merchants[]> {
        try {
            return await this.merchantsRepository.findBy({ id: In(ids)}); // 使用 in 查询条件
        } catch (error) {
            throw new Error('Failed to fetch menus by IDs');
        }
    }
    /**
     * 根据ID异步查找单个商户信息
     * @param id 商户的唯一标识符
     * @returns 返回一个商户对象，如果找不到则返回null
     */
    async findOne(id: number): Promise<merchants | null> {
        return await this.merchantsRepository.findOneBy({ id });
    }
    
    /**
     * 创建新的商户信息
     * @param merchants 要创建的新商户对象
     * @returns 返回保存后的商户对象
     */
    async create(merchants: merchants): Promise<merchants> {
        return await this.merchantsRepository.save(merchants);
    }
    
    /**
     * 更新指定ID的商户信息
     * @param id 商户的唯一标识符
     * @param merchants 包含更新信息的商户对象
     * @returns 返回更新后的商户对象，如果找不到则返回null
     */
    async update(id: number, merchants: merchants): Promise<merchants | null> {
        await this.merchantsRepository.update(id, merchants);
        return await this.merchantsRepository.findOneBy({ id });
    }
    
    /**
     * 删除指定ID的商户信息
     * @param id 商户的唯一标识符
     * @returns 无返回值
     */
    async remove(id: number): Promise<void> {
        await this.merchantsRepository.delete(id);
    }
    
    /**
     * 根据名称查找商户信息
     * @param name 商户的名称
     * @returns 返回一个包含所有匹配名称的商户数组
     */
    async findByName(name: string): Promise<merchants[]> {
        const queryOptions: FindManyOptions<merchants> = {
            where: { name: ILike(`%${name}%`) } // 使用 where 指定查询条件
        };
        return await this.merchantsRepository.find(queryOptions);
    }
     /**
     * 根据坐标查询最近商户
     * @param longitude 用户的经度
     * @param latitude 用户的纬度
     * @returns 返回一个包含所有匹配距离的商户数组
     */
     async findBylnglat(longitude: number, latitude: number): Promise<merchants[]> {
        const merchants = await this.merchantsRepository.find();   
        // 计算每个商户与用户的距离
        let distances:any[] = [];
        merchants.forEach(merchant => {
            const distance = this.getDistance(latitude,longitude,Number(merchant.latitude),Number(merchant.longitude));
            if(distance<=10){
                distances.push({...merchant,distance})
            }
        });
        // 按距离排序
        distances.sort((a, b) => a.distance - b.distance);
        return distances;
    }
    // 辅助方法：获取距离
    private getDistance(lat1: number, lon1: number, lat2: number, lon2: number): number {
                // 将角度转换为弧度
            var radLat1 = lat1 * Math.PI / 180.0;
            var radLat2 = lat2 * Math.PI / 180.0;
            var deltaLat = radLat2 - radLat1;
            var deltaLon = (lon2 - lon1) * Math.PI / 180.0;
        
            // Haversine公式
            var a = Math.sin(deltaLat/2) * Math.sin(deltaLat/2) +
                    Math.cos(radLat1) * Math.cos(radLat2) * 
                    Math.sin(deltaLon/2) * Math.sin(deltaLon/2);
            var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
            var R = 6371; // 地球平均半径，单位为公里
            var d = R * c;
            return  Number(d.toFixed(2)); // 返回结果，单位为公里
    }
}
